﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace WindowService
{
    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEMTIME
    {
        public ushort wYear;
        public ushort wMonth;
        public ushort wDayOfWeek;
        public ushort wDay;
        public ushort wHour;
        public ushort wMinute;
        public ushort wSecond;
        public ushort wMilliseconds;

        public void FromDateTime(DateTime dateTime)
        {
            wYear = (ushort)dateTime.Year;
            wMonth = (ushort)dateTime.Month;
            wDayOfWeek = (ushort)dateTime.DayOfWeek;
            wDay = (ushort)dateTime.Day;
            wHour = (ushort)dateTime.Hour;
            wMinute = (ushort)dateTime.Minute;
            wSecond = (ushort)dateTime.Second;
            wMilliseconds = (ushort)dateTime.Millisecond;
        }

        public DateTime ToDateTime()
        {
            return new DateTime(wYear, wMonth, wDay, wHour, wMinute, wSecond);
        }
    }  

    public class SystemHelper
    {
        [Flags]
        public enum MessageBroadcastFlags : int
        {
            BSF_QUERY = 0x00000001,
            BSF_IGNORECURRENTTASK = 0x00000002,
            BSF_FLUSHDISK = 0x00000004,
            BSF_NOHANG = 0x00000008,
            BSF_POSTMESSAGE = 0x00000010,
            BSF_FORCEIFHUNG = 0x00000020,
            BSF_NOTIMEOUTIFNOTHUNG = 0x00000040,
            BSF_ALLOWSFW = 0x00000080,
            BSF_SENDNOTIFYMESSAGE = 0x00000100,
            BSF_RETURNHDESK = 0x00000200,
            BSF_LUID = 0x00000400
        }
        [Flags]
        public enum MessageBroadcastRecipients : int
        {
            BSM_ALLCOMPONENTS = 0x00000000,
            BSM_VXDS = 0x00000001,
            BSM_NETDRIVER = 0x00000002,
            BSM_INSTALLABLEDRIVERS = 0x00000004,
            BSM_APPLICATIONS = 0x00000008,
            BSM_ALLDESKTOPS = 0x00000010
        }

        [DllImport("user32.dll", EntryPoint = "BroadcastSystemMessageA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private extern static int BroadcastSystemMessage(MessageBroadcastFlags flags, ref MessageBroadcastRecipients lpInfo, int Msg, int wParam, int lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegisterWindowMessage(string lpString);

        [DllImport("Kernel32.dll")]
        public extern static int FormatMessage(int flag, ref IntPtr source, int msgid, int langid, ref string buf, int size, ref IntPtr args);
        [DllImport("Kernel32.dll")]
        public static extern bool SetLocalTime(ref SYSTEMTIME time);  
        public static void Restart(int timeOut)
        {
            Log.WriteLog("SystemHelper Restart Computer, timeOut is " + timeOut, LogType.Trace);
            if (timeOut <= 0) Process.Start("shutdown.exe", "-s");
            else Process.Start("shutdown.exe", "-r -t " + timeOut);
        }
        public static void ShutDown(int timeOut)
        {
            Log.WriteLog("SystemHelper ShutDown Computer, timeOut is " + timeOut, LogType.Trace);
            if (timeOut <= 0) Process.Start("shutdown.exe", "-r");
            else Process.Start("shutdown.exe", "-s -t " + timeOut);
        }
        public static void LogOff()
        {
            Log.WriteLog("SystemHelper LogOff", LogType.Trace);
            Process.Start("shutdown.exe", "-l");
        }
        public static void broadcastMessage(
            string messageType, int wParam = 0, int lParam = 0, 
            MessageBroadcastFlags flags = MessageBroadcastFlags.BSF_POSTMESSAGE,
            MessageBroadcastRecipients recipients = MessageBroadcastRecipients.BSM_ALLCOMPONENTS | MessageBroadcastRecipients.BSM_ALLDESKTOPS | MessageBroadcastRecipients.BSM_APPLICATIONS
            ) 
        {
            int messageFlag = registerMessage(messageType);
            Log.WriteLog("SystemHelper Register System Message " + messageType + ", MessageID is" + messageFlag, LogType.Trace);
            if (messageFlag != 0)
            {
                int messageId = BroadcastSystemMessage(flags, ref recipients, messageFlag, wParam, lParam);
                if (messageId == 0)
                {
                    int errCode = Marshal.GetLastWin32Error();
                    Log.WriteLog("SystemHelper Broadcast message error:" + GetSysErrMsg(errCode), LogType.Error);
                    return;
                }
                Log.WriteLog("SystemHelper Broadcast System Message " + messageType + "(wParam=" + wParam + ",lParam=" + lParam + ") Success", LogType.Trace);
            }
        }
        //注册系统消息字符串
        public static int registerMessage(string messageFlag)
        {
             int messageId = RegisterWindowMessage(messageFlag);
             if (messageId == 0)
             {
                 int errCode = Marshal.GetLastWin32Error();
                 Log.WriteLog("SystemHelper Register message error:" + GetSysErrMsg(errCode), LogType.Error);
             }
             return messageId;
        }
        // <summary>
        /// 获取系统错误信息描述
        /// </summary>
        /// <param name="errCode">系统错误码</param>
        /// <returns></returns>
        public static string GetSysErrMsg(int errCode)
        {
            IntPtr tempptr = IntPtr.Zero;
            string msg = null;
            FormatMessage(0x1300, ref tempptr, errCode, 0, ref msg, 255, ref tempptr);
            return msg;
        }
        private static IntPtr mallocIntptr(string strData)
        {
            //先将字符串转化成字节方式   
            Byte[] btData = System.Text.Encoding.Default.GetBytes(strData);

            //申请非拖管空间   
            IntPtr m_ptr = Marshal.AllocHGlobal(btData.Length);

            //给非拖管空间清０    
            Byte[] btZero = new Byte[btData.Length + 1]; //一定要加1,否则后面是乱码，原因未找到   
            Marshal.Copy(btZero, 0, m_ptr, btZero.Length);

            //给指针指向的空间赋值   
            Marshal.Copy(btData, 0, m_ptr, btData.Length);

            return m_ptr;
        }  


        /// <summary>
        /// 时间戳转为C#格式时间
        /// </summary>
        /// <param name="timeStamp">Unix时间戳格式</param>
        /// <returns>C#格式时间</returns>
        public static DateTime GetTime(string timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }
        /// <summary>
        /// DateTime时间格式转换为Unix时间戳格式
        /// </summary>
        /// <param name="time"> DateTime时间格式</param>
        /// <returns>Unix时间戳格式</returns>
        public static int ConvertDateTimeInt(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (int)(time - startTime).TotalSeconds;
        }

        public static void setClock(DateTime dt)
        {
            SYSTEMTIME systemTime = new SYSTEMTIME();
            systemTime.FromDateTime(dt);
            SetLocalTime(ref systemTime);
        }
    }

}
